﻿using System;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using PasteLoggerBoard.HttpApi.Host.handler;
using PasteLoggerBoard.redismodel;
using Z.EntityFramework.Plus;

namespace PasteLoggerBoard
{
    /// <summary>
    /// 统计每日的数据，需要锁定，防止多次统计
    /// </summary>
    public class CollectHostedService : IHostedService
    {

        private readonly IServiceProvider _serviceProvider;
        private System.Timers.Timer _timer;
        private readonly CollectHandler _collectHandler;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="serviceProvider"></param>
        /// <param name="collectHandler"></param>
        public CollectHostedService(IServiceProvider serviceProvider, CollectHandler collectHandler)
        {
            _serviceProvider = serviceProvider;
            _collectHandler = collectHandler;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public Task StartAsync(CancellationToken cancellationToken)
        {
            Console.WriteLine($"{DateTime.Now} StartHostedService.StartAsync");
            _timer = new System.Timers.Timer(50000);
            _timer.Elapsed += _timer_Elapsed;
            _timer.Start();
            return Task.CompletedTask;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            var _lock_collect = "lock.collect.data";
            var _appCache = _serviceProvider.GetRequiredService<IAppCache>();
            var _lock = await _appCache.LockAsync(_lock_collect, 20);
            if (_lock)
            {
                var _now = DateTime.Now;
                if (_now.Minute == 0)
                {
                    using var _scope = _serviceProvider.CreateScope();
                    using var _dbContext = _scope.ServiceProvider.GetRequiredService<IPasteLoggerBoardDbContext>();
                    var _currentdate = _now.AddMinutes(-1);
                    if (_now.Hour != _currentdate.Hour)
                    {
                        await _collectHandler.CollectPathHour(_dbContext, _currentdate, _appCache);
                        await _collectHandler.CollectLevelHour(_dbContext, _currentdate, _appCache);
                        await _collectHandler.CollectStatusHour(_dbContext, _currentdate, _appCache);
                        await _collectHandler.CollectClientIpHour(_dbContext, _currentdate, _appCache);
                        var apps = await _dbContext.AppInfo.Where(x => true).AsNoTracking().ToListAsync();
                        if (apps != null && apps.Count > 0)
                        {
                            foreach (var item in apps)
                            {
                                if (item.InfoSaveHour <= 0)
                                {
                                    item.InfoSaveHour = 4;
                                }
                                var _ago = DateTime.Parse(DateTime.Now.AddHours((0 - item.InfoSaveHour)).ToString("yyyy-MM-dd HH:00:00"));
                                //这里会超时
                                await _dbContext.LogInfo.Where(xy => xy.DateLog < _ago).DeleteAsync();
                            }
                        }
                    }
                    if (_now.Hour == 0)
                    {
                        var _currentday = _now.AddMinutes(-1);
                        if (_currentday.Day != _now.Day)
                        {
                            //上一天的
                            await _collectHandler.CollectLevelDay(_dbContext, _currentdate);
                            await _collectHandler.CollectPathDay(_dbContext, _currentday);
                            await _collectHandler.CollectStatusDay(_dbContext, _currentday);
                            //var d = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd 00:00:00"));
                            //var _ago = d.AddDays(-1);
                            //_dbContext.LogInfo.Where(xy => xy.DateLog < _ago).Delete();
                        }
                    }
                    if (_now.Hour == 3)
                    {
                        var apps = await _dbContext.AppInfo.Where(x => true).AsNoTracking().ToListAsync();
                        if (apps != null && apps.Count > 0)
                        {
                            foreach (var item in apps)
                            {
                                if (item.WarnSaveDay <= 0)
                                {
                                    item.WarnSaveDay = 60;
                                }
                                var _monthwarning = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd 00:00:00")).AddDays((0 - item.WarnSaveDay));
                                await _dbContext.LogWarning.Where(x => x.DateLog < _monthwarning && x.AppName == item.AppName).DeleteAsync();
                                if (item.ErrorSaveDay <= 0)
                                {
                                    item.ErrorSaveDay = 60;
                                }
                                var _montherror = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd 00:00:00")).AddDays((0 - item.ErrorSaveDay));
                                await _dbContext.LogError.Where(x => x.DateLog < _montherror).DeleteAsync();
                            }
                        }
                    }
                    _dbContext.Dispose();
                    _scope.Dispose();
                }
                _appCache.UnLock(_lock_collect);
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public Task StopAsync(CancellationToken cancellationToken)
        {
            if (_timer != null)
            {
                _timer.Stop();
                _timer.Dispose();
            }
            return Task.CompletedTask;
        }
    }
}
